package com.nfcpay;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.charset.Charset;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.Signature;
import java.security.SignatureException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;

import android.app.Activity;
import android.content.Intent;
import android.nfc.FormatException;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.NfcAdapter.CreateNdefMessageCallback;
import android.nfc.NfcEvent;
import android.os.Bundle;
import android.os.Environment;
import android.os.Parcelable;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
//TODO escrever na tag
public class VendedorActivity extends Activity implements CreateNdefMessageCallback{
	private static final String TAG = "vendedorActivity";
	
	NfcAdapter mNfcAdapter;
	private TextView 	mRecibo;
	private TextView 	mStatus;
	private Button 		mEnviarReciboVendedor;
	private Button		mNovaTransacao;
	private Bundle 		mBundleMsg;
	private String 		mMsg = null;
	private int 		msgCount = 0;
	private byte[] 		assinatura;
	
	@Override
	public void onCreate(Bundle savedInstanceState) {
		Log.i(TAG, "[ACTIVITY] onCreate");
		super.onCreate(savedInstanceState);
		mBundleMsg = this.getIntent().getExtras();
		//se recebeu a mensagem com o recibo e assinatura, seta-os
		if(mBundleMsg != null && mBundleMsg.getByteArray("assinatura") != null){
			mMsg = mBundleMsg.getString("msg");
			assinatura = mBundleMsg.getByteArray("assinatura");
		}
		setContentView(R.layout.vendedor);
		//setando widgets
		mRecibo = (TextView) findViewById(R.id.tRecibo);
		mStatus = (TextView) findViewById(R.id.tStatus);
		mStatus.setVisibility(mStatus.INVISIBLE);
		mEnviarReciboVendedor = (Button) findViewById(R.id.bEnviar);
		mNovaTransacao = (Button) findViewById(R.id.bNovaTransacao);
		// Verifica por NFC disponível
		mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
		if(mNfcAdapter == null){
			Toast.makeText(this, "NFC não está disponível", Toast.LENGTH_LONG).show();
			finish();
			return;
		}
		//Registra callBack
		mNfcAdapter.setNdefPushMessageCallback(this, this);
	}
	
	@Override
	protected void onStart() {
		Log.i(TAG, "[ACTIVITY] onStart");
		super.onStart();
	}
	
	@Override
	protected void onResume() {
		Log.i(TAG, "[ACTIVITY] onResume");
		super.onResume();
		boolean isAssinaturaOk; 
		if(mMsg!=null){
			if(conferirAssinatura(mMsg, assinatura)){
				efetuarPagameto(mMsg);
			}else{
				mStatus.setVisibility(mStatus.VISIBLE);
				mStatus.setText("Assinatura inválida");
			}
		}
//		if(NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())){
//			processIntent(getIntent());
//		}
	}
	
	final static String pagamentoEfetuado = "pagamento efetuado";
	final static String pagamentoNegado = "pagamento negado";
	final static String pagamentoNaoConcluido = "pagamento não concluido";
	
    private void efetuarPagameto(String mMsg2) {
    	String status = enviarAssinaturaServidor(mMsg2);
    	//
    	mStatus.setVisibility(mStatus.VISIBLE);
    	if(status.equals(pagamentoEfetuado)){
    		mStatus.setText(pagamentoEfetuado);
    		mNovaTransacao.setVisibility(mNovaTransacao.VISIBLE);
    	}else if(status.equals(pagamentoNegado)){
    		mStatus.setText(pagamentoNegado);
    	}else if(status.equals(pagamentoNaoConcluido)){
    		mStatus.setText(pagamentoNaoConcluido);
    	}
	}

	private String enviarAssinaturaServidor(String mMsg2) {
		//TODO servidor recebe e responde status
		return pagamentoEfetuado;
	}

	private boolean conferirAssinatura(String mMsg2, byte[] signature) {
		//TODO inicio verificação
		//Obtendo o certificado digital do arquivo
		File dir = Environment.getExternalStorageDirectory();
		File certPub = new File(dir, "cert.der");
		byte[] encodedCert = new byte[(int) certPub.length()];
		
		//TODO retirar
		//criando fileInputStream certificado
		FileInputStream fisCert = null;
		String teste = null;
		try {
			fisCert = new FileInputStream(certPub);
			fisCert.read(encodedCert);
			teste = fisCert.toString();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return false;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		ByteArrayInputStream bis = new ByteArrayInputStream(encodedCert);
		Certificate c = null;
		try {
			//obtendo fábrica de certificados X.509
			CertificateFactory cf = CertificateFactory.getInstance("X.509");
			//Gerando objeto Certificate com o inputStream do arquivo
			c = cf.generateCertificate(bis);
			fisCert.close();
		} catch (CertificateException e) {
			e.printStackTrace();
			return false;
		} catch (IOException e) {
			e.printStackTrace();
			return false;
		}
		//Atribuindo a chave pública na assinatura
		Signature sig = null;
		try {
			sig = Signature.getInstance("SHA1WithRSA");
			sig.initVerify(c.getPublicKey());
		} catch (NoSuchAlgorithmException e1) {
			e1.printStackTrace();
			return false;
		} catch (InvalidKeyException e) {
			e.printStackTrace();
			return false;
		}
		boolean ok = false;
		try {
			//dados da mensagem a serem verificados
			sig.update(mMsg2.getBytes());
			//verificando assinatura
			ok = sig.verify(signature);
		} catch (SignatureException e) {
			e.printStackTrace();
			return false;
		}
		return ok;
		
	}

	public void mudaRecibo(View view){
    	switch (msgCount) {
		case 0:
			mRecibo.setText("empresa xpto/ntotal 20R$");
			msgCount++;
			break;
		case 1:
			mRecibo.setText("empresa xpto/ntotal 30R$");
			msgCount++;
			break;
		case 2:
			mRecibo.setText("empresa xpto/ntotal 50R$");
			msgCount = 0;
			break;
		default:
			break;
		}
    }

	@Override
	public NdefMessage createNdefMessage(NfcEvent event) {
		String text = "vendedor;"+mRecibo.getText().toString();
		NdefRecord appRecord = NdefRecord.createApplicationRecord("com.nfcpay");
		NdefRecord mimeRecord = new NdefRecord(NdefRecord.TNF_MIME_MEDIA,
			    "application/vnd.com.nfcpay".getBytes(Charset.forName("US-ASCII")),
			    new byte[0], text.getBytes(Charset.forName("US-ASCII")));
		//escrevendo 2 records
		NdefMessage msg = new NdefMessage(new NdefRecord[] {
				mimeRecord, appRecord});
        return msg;
	}
	
	 @Override
	    public void onNewIntent(Intent intent) {
	        // onResume gets called after this to handle the intent
	        setIntent(intent);
	    }
	
    /**
     * Parses the NDEF Message from the intent and prints to the TextView
     */
    void processIntent(Intent intent) {
        mRecibo = (TextView) findViewById(R.id.tRecibo);
        Parcelable[] rawMsgs = intent.getParcelableArrayExtra(
                NfcAdapter.EXTRA_NDEF_MESSAGES);
        // only one message sent during the beam
        NdefMessage msg = (NdefMessage) rawMsgs[0];
        // record 0 contains the MIME type, record 1 is the AAR, if present
        mRecibo.setText(new String(msg.getRecords()[0].getPayload()));
    }
}
